﻿using AiQiuQuan.Sport.Core;
using AiQiuQuan.Sport.Model;
using AiQiuQuan.Sport.Model.Enums;
using AiQiuQuan.Sport.Model.Models;
using AiQiuQuan.Sport.WebApi.Entities;
using Microsoft.EntityFrameworkCore;

namespace AiQiuQuan.Sport.WebApi.Services.Impl
{
    /// <summary>
    /// 场馆支付退款逻辑
    /// </summary>
    public partial class PayService
    {
        /// <summary>
        /// 场馆订单逻辑
        /// </summary>
        private async Task<UnaryResult<PayResultDto>> PayVenueOrderAsync(PayRequestDto request, PayOrderInnerInfo payInner, PayResultDto payResult, BaseUser user)
        {
            var siteOrder = await _siteOrderRepository.AsNoTracking().FirstOrDefaultAsync(m => m.ID == request.OrderId && m.SO_State == VenueOrderStateEnum.NoPay);
            if (siteOrder == null)
            {
                return UnaryResult.From(10, payResult, $"未查询到业务订单：{request.OrderId}");
            }

            payInner.OrderNo = siteOrder.SO_OrderNo;
            payInner.ProductName = "预定场馆";
            payInner.ProductDescription = siteOrder.SO_OrderRemark;
            payInner.OrderAmount = siteOrder.SO_TotalPrice;
            payInner.DiscountAmount = siteOrder.SO_DiscountPrice;
            payInner.PayAmount = siteOrder.SO_ActualPrice;
            payInner.PayState = PayOrderStateEnum.NotPay;
            payInner.PayRemark = $"{DateTimeOffset.Now},场馆订单";
            payInner.IsCompatibleVenueOrder = true;
            payInner.Payer = user.U_OpenId;

            return UnaryResult.Succeed(payResult);
        }

        /// <summary>
        /// 场馆订单退款逻辑
        /// </summary>
        private async Task<UnaryResult<RefundResultDto>> ExecuteVenueOrderRefundAsync(RefundRequestDto request, PayOrder payOrder, RefundResultDto result)
        {
            var siteOrder = await _siteOrderRepository.FirstOrDefaultAsync(m => m.ID == request.OrderId);
            var isReleaseSite = siteOrder.IsReleaseSite;
            if (siteOrder == null)
            {
                return UnaryResult.From(10, result, $"未查询到场馆订单：{request.OrderId}");
            }

            var oldState = siteOrder.SO_State;
            if (oldState == VenueOrderStateEnum.Completed)
            {
                result.Msg = "订单已完成，重复操作";
                return UnaryResult.From(10, result, result.Msg);
            }

            if (request.CancelType == OrderCancelTypeEnum.User)
            {
                if (oldState == VenueOrderStateEnum.Refund)
                {
                    return UnaryResult.From(10, result, $"未使用状态方可取消订单");
                }

                if (siteOrder.IsWriteOff.HasValue && siteOrder.IsWriteOff.Value)
                {
                    if (!siteOrder.AutoWriteOffTime.HasValue || siteOrder.AutoWriteOffTime.Value.AddDays(7) <= DateTimeOffset.Now)
                    {
                        return UnaryResult.From(10, result, $"订单核销7天后不能退款");
                    }
                }
            }
            else
            {
                if (siteOrder.IsWriteOff.HasValue && siteOrder.IsWriteOff.Value)
                {
                    if (!siteOrder.AutoWriteOffTime.HasValue || siteOrder.AutoWriteOffTime.Value.AddDays(7) <= DateTimeOffset.Now)
                    {
                        return UnaryResult.From(10, result, $"订单核销7天后不能退款");
                    }
                }
            }

            if (request.CancelType == OrderCancelTypeEnum.Venue && oldState != VenueOrderStateEnum.NoPay)
            {
                if (payOrder.PayAmount < payOrder.RefundAmount + request.ApplyAmount)
                {
                    return UnaryResult.From(10, result, $"退款金额大于实际支付金额，请核查");
                }

                if (siteOrder.PayType != PayTypeEnum.VenueMemberCard)
                {
                    var venueAccount = await _venueInfoAccountRepository.FirstOrDefaultAsync(m => m.VenueInfoID == siteOrder.VenueInfoID);
                    if (venueAccount == null)
                    {
                        {
                            return UnaryResult.From(10, result, $"未查询到场馆账户");
                        }
                    }

                    if ((siteOrder.SO_State == VenueOrderStateEnum.NoEvaluate || siteOrder.SO_State == VenueOrderStateEnum.Refund)
                        && venueAccount.CanWithdrawTotal < request.ApplyAmount)
                    {
                        return UnaryResult.From(10, result, $"场馆账户余额不足");
                    }
                }
            }

            //相关数据更新
            siteOrder.SO_CancelTime = DateTimeOffset.Now;
            siteOrder.SO_CancelRole = request.CancelType;
            siteOrder.SO_CancelRemark = request.CancelType.ToEnumDescription();
            siteOrder.SO_State = oldState == VenueOrderStateEnum.NoPay ? VenueOrderStateEnum.Completed : VenueOrderStateEnum.Refund;
            siteOrder.IsReleaseSite = true;
            if (request.CancelReasonID.HasValue)
            {
                var cancelReason = await _ictionarieRepository.FirstOrDefaultAsync(m => m.ID == request.CancelReasonID.Value);
                if (cancelReason != null)
                {
                    siteOrder.SO_CancelReason = cancelReason.ID;
                    siteOrder.SO_CancelRemark = cancelReason.D_DT_Value;
                }
            }

            using (var uow = _unitOfWorkManager.Begin())
            {
                await _siteOrderRepository.UpdateAsync(siteOrder);
                if (!isReleaseSite.GetValueOrDefault())
                {
                    var sitePriceIdList = await _siteDetailRepository.AsNoTracking().Where(m => m.SiteOrderID == siteOrder.ID).Select(m => m.SitePriceListID).ToListAsync();
                    if (sitePriceIdList.Any())
                    {
                        var updateBuilder = await _sitePriceListRepository.UpdatePartialAsync();
                        await updateBuilder.Set(m => m.SPL_State, VenuePriceStateEnum.CanChoice).Where(m => sitePriceIdList.Contains(m.ID)).ExecuteAsync();
                    }
                }

                await uow.CompleteAsync();
            }

            if (oldState == VenueOrderStateEnum.NoPay)
            {
                result.IsSuccess = true;
                result.Msg = "未支付取消订单";
                return UnaryResult.Succeed(result);
            }

            if (request.CancelType == OrderCancelTypeEnum.User && oldState == VenueOrderStateEnum.NoEvaluate)
            {
                result.IsSuccess = true;
                result.Msg = "请联系场馆管理员进行退款";
                return UnaryResult.From(10, result, result.Msg);
            }

            //根据场馆退款规则计算实际退款金额
            var unaryResult = await CalculateVenueRefundAmountAsync(request, siteOrder, payOrder, result);
            return unaryResult;
        }

        /// <summary>
        /// 计算场馆订单退款金额
        /// </summary>
        private async Task<UnaryResult<RefundResultDto>> CalculateVenueRefundAmountAsync(RefundRequestDto request, SiteOrder siteOrder, PayOrder payOrder, RefundResultDto result)
        {
            //用户取消订单
            if (request.CancelType == OrderCancelTypeEnum.User)
            {
                //查询退款规则
                var refundRuleList = await _venueInfoRefundRuleConfigRepository.Where(m => m.VenueInfoID == siteOrder.VenueInfoID && m.VIRRC_IsEffect)
                                            .OrderByDescending(m => m.VIRRC_Hours).ToListAsync();
                //查询订单使用最开始时间
                //var queryable = from siteOrderDetail in _siteDetailRepository.AsNoTracking()
                //                join sitePrice in _sitePriceListRepository.AsNoTracking()
                //                on siteOrderDetail.SitePriceListID equals sitePrice.ID
                //                where siteOrderDetail.SiteOrderID == siteOrder.ID
                //                orderby sitePrice.SPL_TimeSlot
                //                select sitePrice;
                var price = await _siteDetailRepository.AsNoTracking().Where(m => m.SiteOrderID == siteOrder.ID).OrderBy(m => m.SiteStartTime).FirstOrDefaultAsync();
                //计算应退退款金额
                //使用时间大于取消时间+规则限定时间
                var priceDate = DateTime.Parse(price.SiteDate.Value.ToString("yyyy-MM-dd") + " " + price.SiteStartTime + ":00");
                var ruleConf = refundRuleList.FirstOrDefault(m => priceDate > DateTime.Now.AddHours(m.VIRRC_Hours));
                if (refundRuleList.Any() && ruleConf == null)
                {
                    //非场馆会员卡支付
                    //有退款规则，但没有找到，直接打入对应场馆账户,更改订单为退款售后状态
                    var orderBuilder = await _siteOrderRepository.UpdatePartialAsync();
                    await orderBuilder.Set(m => m.SO_State, VenueOrderStateEnum.Refund)
                        .Set(m => m.UpdateTime, DateTimeOffset.Now)
                        .Set(m => m.IsWriteOff, true)
                        .Set(m => m.AutoWriteOffTime, DateTimeOffset.Now)
                        .Where(m => m.ID == siteOrder.ID).ExecuteAsync();
                    if (payOrder.PayType != PayTypeEnum.VenueMemberCard)
                    {
                        var venueAccountDetailList = new List<VenueInfoAccountDetailAddDto>
                        {
                            new VenueInfoAccountDetailAddDto
                            {
                                VenueID = siteOrder.VenueInfoID,
                                Amount = payOrder.PayAmount,
                                OperateType = VenueAccountOperateEnum.Add,
                                SourceType = VenueAccountSourceEnum.PlatServiceFee,
                                Remark = $"取消订单：{siteOrder.SO_OrderNo};退款后结余总金额：{payOrder.PayAmount}"
                            }
                        };
                        await _capPublisher.PublishAsync(MessageTopic.VENUE_ACCOUNT_DETAIL_ADD, venueAccountDetailList);
                    }

                    result.ApplyAmount = 0;
                    result.RefundAmount = 0;
                    result.ServiceChargeAmount = payOrder.PayAmount;
                    result.IsSuccess = true;
                    result.Msg = "全额转入场馆账户";

                    return UnaryResult.Succeed(result);
                }

                var retainAmount = payOrder.PayAmount - payOrder.RefundAmount;
                var refundAmount = ruleConf == null ? retainAmount : retainAmount * ruleConf.VIRRC_RefundRatio / 100;
                result.RefundAmount = refundAmount;
                result.ServiceChargeAmount = retainAmount - refundAmount;
                result.ApplyAmount = retainAmount;
            }
            //场馆取消
            else
            {
                result.RefundAmount = request.ApplyAmount;
                result.ApplyAmount = request.ApplyAmount;
                result.ServiceChargeAmount = 0;
            }

            return UnaryResult.Succeed(result);
        }
    }
}
